package com.ctshk.common.utils;

import com.alibaba.fastjson.JSON;
import com.amadeus.Amadeus;
import com.amadeus.Params;
import com.amadeus.exceptions.ResponseException;
import com.amadeus.resources.FlightOfferSearch;
import com.amadeus.resources.FlightOrder;
import com.amadeus.resources.FlightPrice;
import com.ctshk.common.enums.AmadeusCode;
import org.apache.commons.lang3.StringUtils;

import java.util.Arrays;

/**
 * Amadeus飞机票工具类
 *
 * @author 胡广
 * @since 2021/2/3
 */
public class AmadeusUtil {

    private static String CLIENT_ID = "TYSFmPPKALHfgZGMWTyb2904zbjN2Yxp";
    private static String CLIENT_SECRET = "DrTr32rj8pC0GaCb";
    public static Amadeus amadeus = Amadeus.builder(CLIENT_ID, CLIENT_SECRET).build();

    public static void buildAmadeus() {
        buildAmadeus(CLIENT_ID, CLIENT_SECRET);
    }

    public static synchronized void buildAmadeus(String reClientId, String reClientSecret) {
        CLIENT_ID = reClientId;
        CLIENT_SECRET = reClientSecret;
        amadeus = Amadeus.builder(CLIENT_ID, CLIENT_SECRET).build();
    }

    /**
     * 根据搜索条件返回航班优惠列表的json串。
     *
     * @param originLocationCode      必填，城市/机场 国际航空运输协会代码 旅行者将从其出发，例如，波士顿的BOS
     * @param destinationLocationCode 必填，城市/机场 国际航空运输协会代码 旅行者前往的目的地，例如巴黎的PAR
     * @param departureDate           必填，旅行者从原点出发前往目的地的日期。日期在ISO 8601 YYYY-MM-DD格式，例如2017-12-25
     * @param returnDate              旅行者离开目的地返回原点的日期。如果未指定此参数，则仅找到单程路线。如果指定了此参数，则仅找到往返行程。日期在ISO 8601 YYYY-MM-DD格式，例如2018-02-28
     * @param adults                  必填，默认值1，成人旅客人数（出发日期12岁以上）
     * @param children                各自拥有独立座位的儿童旅行者（大于2岁且小于12岁）的数量。如果指定，则此数字应大于或等于0
     * @param infants                 婴儿旅客的数量（离开日年龄小于或等于2）。婴儿在成年旅客的腿上旅行，因此婴儿人数不得超过成人人数。如果指定，则此数字应大于或等于0
     * @param travelClass             可用值：ECONOMY, PREMIUM_ECONOMY, BUSINESS, FIRST，大部分飞行时间都应花在质量更高或更高的机舱中。可接受的旅行舱为经济舱，高级经济舱，商务舱或头等舱。如果未指定旅行等级，则搜索将考虑任何旅行等级
     * @param includedAirlineCodes    如果指定，则航班报价将至少包括这些航空公司之一营销的每个航段。航空公司指定为国际航空运输协会航空公司代码 并以逗号分隔，例如6X，7X，8X
     * @param excludedAirlineCodes    如果指定，则航班优惠将排除其中一家航空公司销售的所有航班。航空公司指定为国际航空运输协会航空公司代码 并以逗号分隔，例如6X，7X，8X
     * @param nonStop                 默认值:false,如果设置为true，则搜索将仅查找从起点到目的地的航班，且之间不停靠
     * @param currencyCode            航班优惠的首选货币。货币在ISO 4217 格式，例如EUR表示欧元
     * @param maxPrice                每位旅客的最高价格。默认情况下，没有限制。如果指定，则该值应为无小数的正数
     * @param max                     默认值:250,返回的最大航班优惠数量。如果指定，则该值应大于或等于1
     * @return 航班列表的jsonString
     * @throws ResponseException
     */
    public static String shoppingFlightOffersSearchJson(String originLocationCode, String destinationLocationCode, String departureDate,
                                                        String returnDate, int adults, Integer children, Integer infants, AmadeusCode travelClass, String includedAirlineCodes,
                                                        String excludedAirlineCodes, boolean nonStop, String currencyCode, Integer maxPrice, Integer max) throws ResponseException {
        FlightOfferSearch[] fs = shoppingFlightOffersSearch(originLocationCode, destinationLocationCode, departureDate, returnDate, adults, children, infants, travelClass.toString(), includedAirlineCodes, excludedAirlineCodes, nonStop, currencyCode, maxPrice, max);
        return JSON.toJSONString(Arrays.asList(fs));
    }

    /**
     * 根据搜索条件返回航班优惠列表。
     *
     * @param originLocationCode      必填，城市/机场 国际航空运输协会代码 旅行者将从其出发，例如，波士顿的BOS
     * @param destinationLocationCode 必填，城市/机场 国际航空运输协会代码 旅行者前往的目的地，例如巴黎的PAR
     * @param departureDate           必填，旅行者从原点出发前往目的地的日期。日期在ISO 8601 YYYY-MM-DD格式，例如2017-12-25
     * @param returnDate              旅行者离开目的地返回原点的日期。如果未指定此参数，则仅找到单程路线。如果指定了此参数，则仅找到往返行程。日期在ISO 8601 YYYY-MM-DD格式，例如2018-02-28
     * @param adults                  必填，默认值1，成人旅客人数（出发日期12岁以上）
     * @param children                各自拥有独立座位的儿童旅行者（大于2岁且小于12岁）的数量。如果指定，则此数字应大于或等于0
     * @param infants                 婴儿旅客的数量（离开日年龄小于或等于2）。婴儿在成年旅客的腿上旅行，因此婴儿人数不得超过成人人数。如果指定，则此数字应大于或等于0
     * @param travelClass             可用值：ECONOMY, PREMIUM_ECONOMY, BUSINESS, FIRST，大部分飞行时间都应花在质量更高或更高的机舱中。可接受的旅行舱为经济舱，高级经济舱，商务舱或头等舱。如果未指定旅行等级，则搜索将考虑任何旅行等级
     * @param includedAirlineCodes    如果指定，则航班报价将至少包括这些航空公司之一营销的每个航段。航空公司指定为国际航空运输协会航空公司代码 并以逗号分隔，例如6X，7X，8X
     * @param excludedAirlineCodes    如果指定，则航班优惠将排除其中一家航空公司销售的所有航班。航空公司指定为国际航空运输协会航空公司代码 并以逗号分隔，例如6X，7X，8X
     * @param nonStop                 默认值:false,如果设置为true，则搜索将仅查找从起点到目的地的航班，且之间不停靠
     * @param currencyCode            航班优惠的首选货币。货币在ISO 4217 格式，例如EUR表示欧元
     * @param maxPrice                每位旅客的最高价格。默认情况下，没有限制。如果指定，则该值应为无小数的正数
     * @param max                     默认值:250,返回的最大航班优惠数量。如果指定，则该值应大于或等于1
     * @return FlightOfferSearch[] 航班列表
     * @throws ResponseException
     */
    public static FlightOfferSearch[] shoppingFlightOffersSearch(String originLocationCode, String destinationLocationCode, String departureDate,
                                                                 String returnDate, int adults, Integer children, Integer infants, String travelClass, String includedAirlineCodes,
                                                                 String excludedAirlineCodes, boolean nonStop, String currencyCode, Integer maxPrice, Integer max) throws ResponseException {
        Params params = Params.with("originLocationCode", originLocationCode)
                .and("destinationLocationCode", destinationLocationCode)
                .and("departureDate", departureDate)
                .and("adults", adults)
                .and("nonStop", nonStop)
                .and("currencyCode", currencyCode);
        if (StringUtils.isNotEmpty(returnDate)) {
            params.and("returnDate", returnDate);
        }
        if (null != children) {
            params.and("children", children);
        }
        if (null != infants) {
            params.and("infants", infants);
        }
        if (null != travelClass && !AmadeusCode.ALL.equals(travelClass)) {
            params.and("travelClass", travelClass);
        }
        if (StringUtils.isNotEmpty(includedAirlineCodes)) {
            params.and("includedAirlineCodes", includedAirlineCodes);
        }
        if (StringUtils.isNotEmpty(excludedAirlineCodes)) {
            params.and("excludedAirlineCodes", excludedAirlineCodes);
        }
        if (null != maxPrice) {
            params.and("maxPrice", maxPrice);
        }
        if (null != max) {
            params.and("max", max);
        }
        FlightOfferSearch[] flightOffersSearches = amadeus.shopping.flightOffersSearch.get(params);
        return flightOffersSearches;
    }

    public static FlightOfferSearch[] shoppingFlightOffersSearchPost(String body) throws ResponseException {
        FlightOfferSearch[] flightOffersSearches = amadeus.shopping.flightOffersSearch.post(body);
        return flightOffersSearches;
    }

    /**
     * 查询航班价格
     * include可用值: credit-card-fees, bags, other-services, detailed-fare-rules
     * credit-card-fees 获取预订中所用的信用卡费用
     * bags 获得额外的bags选项
     * other-services 获得服务选项
     * detailed-fare-rules 获取详细票价规则选项
     *
     * @param body FlightOfferSearch[]搜索条件
     * @return
     */
    public static FlightPrice shoppingFlightOffersSearchPricing(FlightOfferSearch[] body) throws ResponseException {
        FlightPrice flightPricing = amadeus.shopping.flightOffersSearch.pricing.post(
                body,
                Params.with("include", "other-services")
                        .and("forceClass", "false"));
        return flightPricing;
    }

    /**
     * 预订航班单(必须先查询航班价格才能预订航班)
     *
     * @param body 订单消息体
     * @return
     * @throws ResponseException
     */
    public static FlightOrder bookingFlightOrders(String body) throws ResponseException {
        FlightOrder createdOrder = amadeus.booking.flightOrders.post(body);
        return createdOrder;
    }

    /**
     * 取消航班订单
     * @param flightOrderId 航班订单Id
     * @return
     * @throws ResponseException
     */
    public static FlightOrder cancelFlightOrder(String flightOrderId) throws ResponseException {
        FlightOrder cancelOrder = amadeus.booking.flightOrder(flightOrderId).delete();
        return  cancelOrder;
    }



}
